import { Context, Next } from 'koa';
import Joi from 'joi';
import { AppError } from '@/middlewares/error';
import { MulterFile } from '@/types/express';

/**
 * 验证目标类型
 */
export type ValidateTarget = 'body' | 'query' | 'params' | 'headers';

/**
 * 验证选项
 */
export interface ValidateOptions {
  allowUnknown?: boolean;
  stripUnknown?: boolean;
  abortEarly?: boolean;
}

/**
 * 创建验证中间件
 */
export const validate = (
  schema: Joi.ObjectSchema,
  target: ValidateTarget = 'body',
  options: ValidateOptions = {}
) => {
  const defaultOptions: ValidateOptions = {
    allowUnknown: false,
    stripUnknown: true,
    abortEarly: false,
    ...options,
  };

  return async (ctx: Context, next: Next): Promise<void> => {
    try {
      let dataToValidate: unknown;

      // 根据目标选择要验证的数据
      switch (target) {
        case 'body':
          dataToValidate = ctx.request.body;
          break;
        case 'query':
          dataToValidate = ctx.query;
          break;
        case 'params':
          dataToValidate = ctx.params;
          break;
        case 'headers':
          dataToValidate = ctx.headers;
          break;
        default:
          throw new AppError('无效的验证目标', 500);
      }

      // 执行验证
      const { error, value } = schema.validate(dataToValidate, defaultOptions);

      if (error) {
        // 格式化错误信息
        const errorMessage = error.details
          .map(detail => detail.message)
          .join('; ');
        
        throw new AppError(errorMessage, 400);
      }

      // 将验证后的数据重新赋值
      switch (target) {
        case 'body':
          ctx.request.body = value;
          break;
        case 'query':
          ctx.query = value;
          break;
        case 'params':
          ctx.params = value;
          break;
        case 'headers':
          // 通常不修改 headers
          break;
      }

      await next();
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw new AppError('数据验证失败', 400);
    }
  };
};

/**
 * 验证请求体
 */
export const validateBody = (schema: Joi.ObjectSchema, options?: ValidateOptions) => {
  return validate(schema, 'body', options);
};

/**
 * 验证查询参数
 */
export const validateQuery = (schema: Joi.ObjectSchema, options?: ValidateOptions) => {
  return validate(schema, 'query', options);
};

/**
 * 验证路径参数
 */
export const validateParams = (schema: Joi.ObjectSchema, options?: ValidateOptions) => {
  return validate(schema, 'params', options);
};

/**
 * 验证请求头
 */
export const validateHeaders = (schema: Joi.ObjectSchema, options?: ValidateOptions) => {
  return validate(schema, 'headers', options);
};

/**
 * 组合验证中间件
 */
export const validateAll = (schemas: {
  body?: Joi.ObjectSchema;
  query?: Joi.ObjectSchema;
  params?: Joi.ObjectSchema;
  headers?: Joi.ObjectSchema;
}, options?: ValidateOptions) => {
  return async (ctx: Context, next: Next): Promise<void> => {
    // 按顺序验证各个部分
    if (schemas.params) {
      await validateParams(schemas.params, options)(ctx, async () => {});
    }
    
    if (schemas.query) {
      await validateQuery(schemas.query, options)(ctx, async () => {});
    }
    
    if (schemas.headers) {
      await validateHeaders(schemas.headers, options)(ctx, async () => {});
    }
    
    if (schemas.body) {
      await validateBody(schemas.body, options)(ctx, async () => {});
    }

    await next();
  };
};

/**
 * 自定义验证器
 */
export class CustomValidator {
  /**
   * 验证邮箱唯一性（示例）
   */
  static async validateEmailUnique(_email: string): Promise<boolean> {
    // 这里应该查询数据库检查邮箱是否已存在
    // 示例代码，实际应该注入用户服务
    try {
      // const userService = new UserService();
      // const existingUser = await userService.findByEmail(email);
      // return !existingUser;
      return true; // 临时返回 true
    } catch {
      return false;
    }
  }

  /**
   * 验证用户名唯一性（示例）
   */
  static async validateUsernameUnique(_username: string): Promise<boolean> {
    // 这里应该查询数据库检查用户名是否已存在
    try {
      // const userService = new UserService();
      // const existingUser = await userService.findByUsername(username);
      // return !existingUser;
      return true; // 临时返回 true
    } catch {
      return false;
    }
  }

  /**
   * 验证文件类型
   */
  static validateFileType(file: MulterFile, allowedTypes: string[]): boolean {
    if (!file || !file.mimetype) {
      return false;
    }
    
    return allowedTypes.includes(file.mimetype);
  }

  /**
   * 验证文件大小
   */
  static validateFileSize(file: MulterFile, maxSize: number): boolean {
    if (!file || typeof file.size !== 'number') {
      return false;
    }
    
    return file.size <= maxSize;
  }

  /**
   * 验证图片文件
   */
  static validateImageFile(file: MulterFile, maxSize: number = 5 * 1024 * 1024): boolean {
    const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
    
    return this.validateFileType(file, allowedTypes) && this.validateFileSize(file, maxSize);
  }
}

export default validate;